$(function() {
    var $el = {
        room: $("#room"),
        chessboard: $("#grids"),
        grid: null,
        dialog: $("#dialog"),
        menu : $("#menu"),
        restart : $("#restart"),
        time : $("#time"),
        restartTrigger : $("#restartTrigger"),

        // menu
        confirm:$(".confirm"),
        lvList: $("#lvList"),
        con_restart:$("#con_restart"),
        win:$("#win")
    }


    var tap = 'ontouchstart' in window ? 'touchstart' : 'click';

    var sudoku = {
        data: {},

        time:0,

        curGrid: null,

        init: function(opt) {
            this.data = opt;
            this.data.tm = opt.grid.split('');
            this.draw();
            !this.e_inited && this.initEvent();
            this.inited = true;
            this.time = 0;
            $el.time.html('0:00');
            this.stopTimer();
            this.statTimer();
        },

        statTimer:function() {
            var h,m,s;
            sudoku.timer = setInterval(function() {
                sudoku.time ++;
                h = Math.floor(sudoku.time/3600);
                m = Math.floor(sudoku.time%3600/60);
                s = sudoku.time%3600%60;

                // add zero
                h = (h>0 && h<10) ? "0"+h : h;
                m = (h && m<10) ? "0"+m : m;
                s = (s>0 && s<10) ? "0"+s : s;

                h = h ? h+":" : '';
                m += ":";

                $el.time.html(h+m+s);
            }, 1000);
        },

        stopTimer:function() {
            clearInterval(sudoku.timer);
        },

        restart :  function() {
            this.init( this.data );
        },

        initEvent: function() {
            this.e_inited = true;
            // 棋盘格子监听
            $el.chessboard.on(tap, 'span', function(event) {
                var v = $(this).data('val');
                if (!$(this).hasClass('f')) {
                    sudoku.findFrd(v);
                } else {
                    sudoku.curGrid = $(this);
                    sudoku.showDiaolog();
                    event.stopPropagation();
                }
            });

            // 数字盘
            $el.dialog.on(tap, '.num', function(event) {
                var isMark = $el.dialog.hasClass('mark');
                var num = $(this).data('val');
                if (isMark) {
                    // mark
                    var type = $(this).hasClass('on') ? 'del' : 'add';
                    $(this).toggleClass('on');
                    sudoku.mark(type, num);
                    event.stopPropagation();
                } else {
                    // fill
                    sudoku.fillNum(num);
                }
            });

            // 清除
            $el.dialog.on(tap, '#d-clear', function(event) {
                sudoku.curGrid.data('val', '').data('mark', '').html('');
                sudoku.checkErr('empty');
                // event.stopPropagation();
            });

            // 标记
            $el.dialog.on(tap, '#d-mark', function(event) {
                $el.dialog.toggleClass('mark');
                event.stopPropagation();
            });

            $("body").on(tap, this.closeAll);
        },

        closeAll: function() {
            $el.dialog.hide();
        },

        closeConfirm:function() {
            $(".confirm").hide();
        },

        // 填入数字
        fillNum: function(num) {
            sudoku.curGrid.data('val', num).html(num).data('mark', '');
            sudoku.data.tm[sudoku.curGrid.data('idx')] = num;
            sudoku.findFrd(num);
            sudoku.check();
        },

        // 标记
        mark: function(type, num) {
            // rm data-val
            if (sudoku.curGrid.data('val')) {
                sudoku.curGrid.data('val', '').empty();
            }
            var dataMark = sudoku.curGrid.data('mark') || '';
            if (type === 'del') {
                dataMark = dataMark.replace(num, '');
                sudoku.curGrid.data('mark', dataMark);
                sudoku.curGrid.find('.m' + num).remove();
            } else {
                dataMark += "" + num;
                sudoku.curGrid.append('<i class="m' + num + '">' + num + '</i>').data('mark', dataMark);
            }

        },

        // 查找同类
        findFrd: function(v) {
            $el.grid.each(function(index, grid) {
                if ($(grid).data('val') == v) {
                    $(grid).addClass('active');
                } else {
                    $(grid).removeClass('active');
                }
            });
        },

        // 显示弹窗
        showDiaolog: function() {
            var pos = sudoku.curGrid.position(),
                left, top;
            var val = sudoku.curGrid.data('val'),
                dataMark = sudoku.curGrid.data('mark');
            this.closeAll();
            $el.grid.removeClass('active');
            sudoku.curGrid.addClass("active");

            if (!sudoku.data.gridW || !sudoku.data.gridH) {
                sudoku.data.gridW = sudoku.curGrid.width();
                sudoku.data.gridH = sudoku.curGrid.height();
                sudoku.data.chessboardW = $("#chessboard").width();
                sudoku.data.chessboardH = $("#chessboard").height();
            };

            left = Math.min(pos.left - (150 - sudoku.data.gridW) / 2, sudoku.data.chessboardW - 150);
            left = Math.max(0, left);
            top = Math.min(pos.top - (200 - sudoku.data.gridH) / 2, sudoku.data.chessboardH - 200);
            top = Math.max(0, top);
            $el.dialog.find('.num').removeClass('on');
            if (dataMark) {
                $el.dialog.addClass('mark');
                for (var i = 0, len = dataMark.length; i < len; i++) {
                    $el.dialog.find('.num[data-val=' + dataMark[i] + ']').addClass('on');
                }
            } else {
                $el.dialog.removeClass('mark');
            }
            $el.dialog.css({
                left: left,
                top: top
            }).fadeIn(300);
        },

        // 画棋盘
        draw: function() {
            var html = '';
            for (var i = 0; i < 81; i++) {
                var v = parseInt(this.data.grid[i]) || '';
                var className = v ? "" : 'f ';
                if (i%3==2) className += ' mr';
                if (Math.floor(i/9)%3 ===0) className += ' mt';
                var span = '<span data-idx="' + i + '" data-val="' + v + '" class="'+ className + '">' + v + '</span>';
                html += span;
            }
            $el.chessboard.empty().html(html);
            $el.grid = $("#grids span");
        },

        // 检查是否完成
        check: function() {
            sudoku.checkErr();

            if (sudoku.data.tm.join('') == sudoku.data.answer) {
                sudoku.stopTimer();
                localStorage.setItem('sudoku_lv'+sudoku.data.lv,sudoku.data.p);
                $el.win.find('.lv').html(sudoku.data.lv+1);
                $el.win.find('.time').html( $el.time.html() );
                $el.win.show();
            }
        },

        checkErr:function(ept) {
            // 检查错误
            var i = parseInt(sudoku.curGrid.data('idx')),
                row = Math.floor(i/9),
                col = i%9,
                k = 0,
                gridIdx, $grid;
            var aRow = Math.floor( row/3),
                aCol = Math.floor( col/3);
            var isErr = false;

            for (; k < 9; k++) {
                // 列
                gridIdx = k*9+col ;
                $grid = $el.grid.eq( gridIdx );
                if ($grid.data('idx') != sudoku.curGrid.data('idx')) {
                    if ( $grid.data('val') && $grid.data('val') == sudoku.curGrid.data('val')) {
                        $grid.addClass("err");
                        isErr = true;
                    }else{
                        $grid.removeClass("err");
                    }
                };

                // 行
                gridIdx = k+row*9 ;
                $grid = $el.grid.eq( gridIdx );
                if ($grid.data('idx') != sudoku.curGrid.data('idx')) {
                    if ( $grid.data('val') && $grid.data('val') == sudoku.curGrid.data('val')) {
                        $grid.addClass("err");
                        isErr = true;
                    }else{
                        $grid.removeClass("err");
                    }
                };

                // 区域
                gridIdx = k%3 + Math.floor( k/3 )*9 + 27*aRow + 3*aCol ;
                $grid = $el.grid.eq( gridIdx );
                if ($grid.data('idx') != sudoku.curGrid.data('idx')) {
                    if ( $grid.data('val') && $grid.data('val') == sudoku.curGrid.data('val')) {
                        $grid.addClass("err");
                        isErr = true;
                    }else{
                        $grid.removeClass("err");
                    }
                };
            }

            sudoku.curGrid.toggleClass('err', isErr);
        }
    };

    var game = {
        data: {},

        init: function() {
            var p , $span = $("#difficulty span") , len , html;
            for (var i = 0; i < 5; i++) {
                p = parseInt( localStorage.getItem('sudoku_lv'+i) || 0 );
                len = sudokuData[i].length;
                html = p+"/"+len;
                $span.eq(i).html(html);
            }
            this.initEvent();
        },
        initEvent: function() {
            // close list
            $el.lvList.on(tap, function() {
                sudoku.inited && $(this).hide();
            });

            // choose lv
            $el.lvList.on(tap, '.btn', function() {
                var lv = parseInt($(this).data('lv')),
                    p = parseInt( localStorage.getItem('sudoku_lv'+lv) || 0 );
                var list  = sudokuData[lv];
                var sData = list[p];
                p = p==list.length-1 ? p : p+1;
                sudoku.init({
                    answer: sData.substring(81, 162),
                    grid: sData.substring(0, 81),
                    lv: lv,
                    p : p
                });
            });

            // show menu
            $el.menu.on(tap,function() {
                $el.lvList.show();
            });

            // next lv
            $el.win.on(tap,'.js-nextLv',function() {
                var lv = sudoku.data.lv;
                var p = sudoku.data.p;
                if (sudokuData[lv][p]) {
                    var sData = sudokuData[lv][p];
                    sudoku.init({
                        answer: sData.substring(81, 162),
                        grid: sData.substring(0, 81),
                        lv: lv,
                        p : p+1
                    });
                }else{
                    sudoku.restart();
                }
                sudoku.closeConfirm();
            });

            // show restart confirm
            $el.restartTrigger.on(tap,function() {
                $el.con_restart.show();
            });

            // close
            $el.confirm.on(tap,function() {
                sudoku.closeConfirm();
            });
            $el.confirm.on(tap,'.js-close',function() {
                sudoku.closeConfirm();
            });
            $el.confirm.on(tap,'.inner',function(e) {
                e.stopPropagation();
            });

            // restart
            $el.restart.on(tap,function() {
                sudoku.closeConfirm();
                sudoku.inited && sudoku.restart();
            });
        }
    }

    game.init();

});
